package com.lin.filegraph.utils.parser.astvisitor;

import com.lin.filegraph.utils.parser.node.JMethodNode;
import org.eclipse.jdt.core.dom.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 11:05
 */

public class MethodMccabeVisitor extends ASTVisitor {

    private List<String> listOperators = new ArrayList<String>();
    private JMethodNode methodNode;// 当前分析的方法
    ASTNode methodASTNode;// 当前分析的方法的ASTNode

    public MethodMccabeVisitor(JMethodNode methodNode) {
        this.methodNode = methodNode;
        this.methodASTNode = methodNode.getAstNode();
    }

    public void traverseMethodContent() {
        methodASTNode.accept(this);
    }

    public List<String> getListOperators() {
        return listOperators;
    }

    private void addOperator(ASTNode node) {
        String id = getSimpleTypeName(node);
        listOperators.add(id);
    }

    private void addOperator(ASTNode node, Object name) {
        String id = getSimpleTypeName(node) + "\t" + name.toString();
        listOperators.add(id);
    }

    private String getSimpleTypeName(ASTNode node) {
        return node.getClass().getSimpleName();
    }

    @Override
    public boolean visit(TypeDeclaration node) {
        return false;
    }

    @Override
    public boolean visit(EnumDeclaration node) {
        return false;
    }

    @Override
    public boolean visit(AnonymousClassDeclaration node) {
        return false;
    }

    @Override
    public boolean visit(MethodDeclaration node) {
        //没扫描到一个方法进行加1，这是因为，按照WMC的计算方法来说其实每个方法的初始化圈复杂度是1，但是在这里面进行初始化的时候无法对类中的方法个数不好进行确定，所以
        //在这边处理的时候进行了，碰到方法的申明就进行+1操作来处理
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(Initializer node) {
        //没扫描到一个方法进行加1，这是因为，按照WMC的计算方法来说其实每个方法的初始化圈复杂度是1，但是在这里面进行初始化的时候无法对类中的方法个数不好进行确定，所以
        //在这边处理的时候进行了，碰到方法的申明就进行+1操作来处理
        addOperator(node);
        return true;
    }

    // 获取方法的相关数据
    @Override
    public boolean visit(InfixExpression node) {
        if (node.getOperator() == InfixExpression.Operator.CONDITIONAL_AND
                || node.getOperator() == InfixExpression.Operator.CONDITIONAL_OR) {
            addOperator(node, node.getOperator());
        }
        return true;
    }

    @Override
    public boolean visit(CatchClause node) {
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(ConditionalExpression node) {
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(ForStatement node) {
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(EnhancedForStatement node) {
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(IfStatement node) {
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(SwitchCase node) {
        addOperator(node);
        return true;
    }

    @Override
    public boolean visit(WhileStatement node) {
        addOperator(node);
        return true;
    }
    @Override
    public boolean visit(DoStatement node) {
        addOperator(node);
        return true;
    }
}

